package com.qst.order.service.Impl;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qst.order.config.RabbitMQConfig;
import com.qst.order.domain.*;
import com.qst.order.domain.DTO.*;
import com.qst.order.domain.VO.OrderListVO;
import com.qst.order.mapper.*;
import com.qst.order.service.OrderService;
import com.qst.order.utils.Result;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    private final OrderMapper orderMapper;
    private final OrderItemMapper orderItemMapper;
    private final ProductMapper productMapper;
    private final UserMapper userMapper;
    private final UserAddressMapper userAddressMapper;
    private final MerchantMapper merchantMapper;
    private final MessageTransactionMapper messageTransactionMapper;
    private final RedissonClient redissonClient;
    private final RedisTemplate redisTemplate;
    private final RabbitTemplate rabbitTemplate;
    private final OrderPayMapper orderPayMapper;
    private final NoticeMapper noticeMapper;
    // 锁等待时间和重试次数配置
    private static final int LOCK_WAIT_TIME = 3; // 秒lock_wait_time
    private static final int LOCK_LEASE_TIME = 10; // 秒//lock_lease_time
    private static final int MAX_RETRY_TIMES = 3;// 最大重试次数

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order createOrder(OrderCreatDTO orderCreatDTO, Integer userId) {
        String lockKey = "product_lock:" + orderCreatDTO.getProductId();

        // 尝试获取锁，带有重试机制
        RLock lock = acquireLockWithRetry(lockKey);
        try {
            // 1. 创建订单实体
            Order order = createOrderEntity(orderCreatDTO, userId);

            // 2. 保存订单
            if (orderMapper.insert(order) <= 0) {
                throw new RuntimeException("保存订单失败");
            }

            // 3. 创建并保存订单项
            if (!createAndSaveOrderItem(orderCreatDTO, order)) {
                throw new RuntimeException("保存订单项失败");
            }

            // 4. 扣减库存（放在最后）
            if (!productMapper.decreaseStock(orderCreatDTO.getProductId(), orderCreatDTO.getQuantity())) {
                throw new RuntimeException("更新库存失败");
            }

            return order;
        } finally {
            // 释放锁
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "product", allEntries = true) // 清除所有列表缓存（因库存变化可能影响列表）
    public Order createBatchOrder(OrderBatchRequest orderBatchRequest, Integer userId) {
        // 为批量订单生成一个组合锁key
        StringBuilder lockKeyBuilder = new StringBuilder("batch_order_lock:");
        orderBatchRequest.getSelectedItems().forEach(item ->
                lockKeyBuilder.append(item.getProductId()).append("-"));
        String lockKey = lockKeyBuilder.toString();

        RLock lock = acquireLockWithRetry(lockKey);
        try {
            Order order = new Order();
            order.setOrderNo(generateOrderNo());
            order.setTotalPrice(orderBatchRequest.getTotalPrice());
            order.setStatus("pending");
            order.setPayType("账户支付");
            order.setUserId(userId);
            order.setAddressId(orderBatchRequest.getAddressId());
            order.setCreateTime(LocalDateTime.now());
            orderMapper.insert(order); // 插入订单，生成orderId

            List<OrderItem> orderItemList = new ArrayList<>();
            List<ProductStockUpdate> stockUpdates = new ArrayList<>();

            for (OrderItem item : orderBatchRequest.getSelectedItems()) {
                item.setOrderId(order.getOrderId());
                BigDecimal totalPrice = item.getUnitPrice()
                        .multiply(BigDecimal.valueOf(item.getQuantity()));
                item.setTotalPrice(totalPrice);
                item.setCreateTime(LocalDateTime.now());
                item.setItemStatus("pending");
                item.setItemNo(generateOrderNo());
                orderItemList.add(item);

                ProductStockUpdate stockUpdate = new ProductStockUpdate();
                stockUpdate.setProductId(item.getProductId());
                stockUpdate.setQuantity(item.getQuantity());
                stockUpdates.add(stockUpdate);
            }

            orderItemMapper.insert(orderItemList);

            // 批量更新库存
            int updatedRows = productMapper.batchUpdateStock(stockUpdates);
            if (updatedRows != stockUpdates.size()) {
                throw new RuntimeException("库存更新数量不匹配");
            }

            redisTemplate.opsForValue().set("order:" + order.getOrderId(), order.getOrderNo(), 15, TimeUnit.MINUTES);

            // ============== 本地消息事务表处理 ==============
            // 1. 生成消息唯一ID
            String messageId = UUID.randomUUID().toString().replaceAll("-", "");

            // 2. 插入本地事务表（初始状态：待发送）
            MessageTransaction msgTx = new MessageTransaction();
            msgTx.setMessageId(messageId);
            msgTx.setBusinessType("BATCH_ORDER_PAY_TIMEOUT"); // 批量订单支付超时业务类型
            msgTx.setBusinessId(order.getOrderId()); // 关联订单ID
            msgTx.setMessageContent(order.getOrderId()); // 消息内容为订单ID
            msgTx.setSendStatus(0); // 0-待发送
            msgTx.setHandleStatus(0); // 0-未处理
            msgTx.setCreateTime(new Date());
            messageTransactionMapper.insert(msgTx);

            try {
                // 3. 发送延迟消息（携带消息ID到消息头）
                rabbitTemplate.convertAndSend(
                        RabbitMQConfig.DELAYED_EXCHANGE,
                        RabbitMQConfig.DELAYED_ROUTING_KEY,
                        order.getOrderId(),
                        message -> {
                            message.getMessageProperties().setHeader("x-delay", 6000 * 10 * 15); // 15分钟延迟
                            message.getMessageProperties().setHeader("messageId", messageId); // 携带消息唯一ID
                            return message;
                        }
                );

                // 4. 发送成功：更新本地事务表状态
                MessageTransaction updateTx = new MessageTransaction();
                updateTx.setSendStatus(1); // 1-已发送
                updateTx.setSendTime(new Date());
                updateTx.setSendCount(1); // 发送次数+1
                messageTransactionMapper.update(
                        updateTx,
                        new UpdateWrapper<MessageTransaction>().eq("message_id", messageId)
                );

            } catch (Exception e) {
                // 5. 发送失败：更新本地事务表状态（触发事务回滚）
                MessageTransaction updateTx = new MessageTransaction();
                updateTx.setSendStatus(2); // 2-发送失败
                updateTx.setSendCount(1);
                updateTx.setRemark("延迟消息发送失败：" + e.getMessage());
                messageTransactionMapper.update(
                        updateTx,
                        new UpdateWrapper<MessageTransaction>().eq("message_id", messageId)
                );
                throw new RuntimeException("发送订单超时延迟消息失败", e); // 事务回滚：订单、库存等操作全部撤销
            }
            // ==============================================
            return order;
        } catch (Exception e) {
            throw new RuntimeException("批量创建订单失败", e);
        } finally {
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
    @Override
    public IPage<OrderListVO> getOrderList(Integer page, Integer size, Integer userId, String status,
                                           String orderNO, String startDate, String endDate) {
        try {
            Page<OrderListVO> orderListVOPage = new Page<>(page, size);
            return orderMapper.getOrderListByUserId(orderListVOPage, userId, status,orderNO,startDate,endDate);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public OrderListVO getDetailOrder(Integer orderId) {
      return orderMapper.getOrderByOrderId(orderId);
    }

    @Override
    @Transactional
    public boolean payOrder(PayDTO payDTO, Integer userId) {
        String lockKey = "order_pay_lock:" + payDTO.getOrderNO();
        RLock lock = acquireLockWithRetry(lockKey);
        try {
            // 1. 扣款（确保updateMoney在余额不足时返回false）
            BigDecimal amount = payDTO.getAmount();
            boolean isDeducted = userMapper.updateMoney(userId, amount);

            // 若扣款失败，直接返回false（不执行后续操作）
            if (!isDeducted) {
                log.warn("用户{}支付订单{}失败：余额不足", userId, payDTO.getOrderNO());
                return false; // 明确返回支付失败
            }

            // 2. 扣款成功：更新订单状态为“已支付”
            LambdaUpdateWrapper<Order> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Order::getOrderNo, payDTO.getOrderNO())
                    .set(Order::getPayTime, LocalDateTime.now())
                    .set(Order::getStatus, "paid");
            boolean updateSuccess = orderMapper.update(null, updateWrapper) > 0;

            // 若订单状态更新失败，抛出异常触发事务回滚（避免扣款成功但订单未更新）
            if (!updateSuccess) {
                throw new RuntimeException("订单状态更新失败，支付回滚");
            }

            // 3. 扣款成功：更新订单项状态为“已支付”
            LambdaUpdateWrapper<OrderItem> itemUpdateWrapper = new LambdaUpdateWrapper<>();
            itemUpdateWrapper.eq(OrderItem::getOrderId, payDTO.getOrderId())
                    .set(OrderItem::getItemStatus, "paid");
            orderItemMapper.update(null, itemUpdateWrapper);

            //查询现有金额
            BigDecimal money = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId)).getMoney();
            // 4. 扣款成功：保存支付记录
            OrderPay orderPay = new OrderPay();
            orderPay.setPayTime(LocalDateTime.now());
            orderPay.setUserId(userId);
            orderPay.setMoney(money.subtract(amount));
            orderPay.setPayType("账户支付");
            orderPay.setOrderNo(payDTO.getOrderNO());
            orderPay.setPayMoney(amount);
            int insert = orderPayMapper.insert(orderPay);
            if (insert <= 0) {
                throw new RuntimeException("支付记录保存失败，支付回滚");
            }

            // 5. 删除Redis中的订单缓存
            redisTemplate.delete("order:" + payDTO.getOrderNO());

            // 6. 发送商家通知
            Order paidOrder = orderMapper.selectOne(
                    new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, payDTO.getOrderNO())
            );
            List<OrderItem> orderItems = orderItemMapper.selectList(
                    new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderId, paidOrder.getOrderId())
            );
            List<Notice> notices = new ArrayList<>();
            orderItems.forEach(item -> {
                Notice notice = new Notice();
                notice.setMerchantId(item.getMerchantId());
                notice.setType("order");
                notice.setProductId(item.getProductId());
                notice.setTitle("新订单通知：" + paidOrder.getOrderNo());
                notice.setOrderId(item.getOrderId());
                notice.setIsRead(false);
                notice.setCreateTime(LocalDateTime.now());
                notices.add(notice);
            });
            noticeMapper.insert(notices);

            return true; // 支付成功
        } catch (Exception e) {
            log.error("支付订单异常", e);
            // 异常会触发事务回滚（包括扣款金额回滚）
            throw new RuntimeException("支付失败：" + e.getMessage());
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    @Transactional
    public boolean canceledOrder(Integer orderId) {
        Order order = orderMapper.selectById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }

        String orderStatus = order.getStatus();
        // 检查订单状态，只有未支付或已支付的订单才能取消
        if (!"pending".equals(orderStatus) && !"paid".equals(orderStatus)) {
            return false;
        }

        try {
            // 1. 已支付订单需要先回退金额（退款）
            if ("paid".equals(orderStatus)) {
                // 调用退款逻辑（此处需根据实际业务实现，示例为伪代码）
                boolean refundSuccess = refundOrderAmount(order);
                if (!refundSuccess) {
                    throw new RuntimeException("订单退款失败，无法取消订单");
                }
            }

            // 2. 获取订单项列表（两种状态都需要处理库存）
            List<OrderItem> orderItems = orderItemMapper.selectList(
                    new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderId, orderId)
            );

            // 3. 回退库存（两种状态都需要）
            List<ProductStockUpdate> stockUpdates = new ArrayList<>();
            for (OrderItem item : orderItems) {
                ProductStockUpdate stockUpdate = new ProductStockUpdate();
                stockUpdate.setProductId(item.getProductId());
                stockUpdate.setQuantity(item.getQuantity());
                stockUpdates.add(stockUpdate);
            }
            productMapper.batchIncreaseStock(stockUpdates);

            // 4. 更新订单项状态为已取消
            LambdaUpdateWrapper<OrderItem> itemUpdateWrapper = new LambdaUpdateWrapper<>();
            itemUpdateWrapper.eq(OrderItem::getOrderId, orderId)
                    .set(OrderItem::getItemStatus, "canceled");
            orderItemMapper.update(null, itemUpdateWrapper);

            // 5. 更新订单状态为已取消
            LambdaUpdateWrapper<Order> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Order::getOrderId, orderId)
                    .set(Order::getStatus, "canceled")
                    .set(Order::getCancelTime, LocalDateTime.now());

            int updateResult = orderMapper.update(null, updateWrapper);
            if (updateResult <= 0) {
                throw new RuntimeException("更新订单状态失败");
            }

        } catch (RuntimeException e) {
            log.error("取消订单异常，订单ID：{}", orderId, e);
            throw new RuntimeException("取消订单失败：" + e.getMessage());
        }
        return true;
    }

    /**
     * 回退订单金额（退款逻辑）
     * 实际业务中需根据支付方式（微信/支付宝/余额等）实现具体退款逻辑
     */
    private boolean refundOrderAmount(Order order) {
        // 示例：调用支付服务的退款接口
        // 参数通常包括订单号、退款金额、支付流水号等
        try {
            // 假设paymentService为支付服务接口
            return orderPayMapper.refund(
                    order.getUserId(),
                    order.getOrderNo(),  // 订单编号
                    order.getTotalPrice()// 退款金额
                    ,"账户退款金额"
            );
        } catch (Exception e) {
            log.error("订单退款异常，订单号：{}", order.getOrderNo(), e);
            return false;
        }
    }

    @Override
    public IPage<OrderItem> getByMerchantIdAndStatusWithRelations(IPage<OrderItem> page, Integer merchantId, String status, String startDate, String endDate, String sortType, String searchKey) {
        return orderMapper.getOrderByMerchantId(page, merchantId, status, startDate, endDate, sortType, searchKey);
    }

    //订单监控
    @Override
    public Result<?> listOrders(OrderQueryParam param) {
        // 1. 构建分页对象
        Page<Order> page = new Page<>(param.getPageNum(), param.getPageSize());

        // 2. 构建查询条件
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(param.getOrderNo())) {
            wrapper.like(Order::getOrderNo, param.getOrderNo());
        }
        if (StringUtils.hasText(param.getStatus())) {
            wrapper.eq(Order::getStatus, param.getStatus());
        }
        if (param.getStartDate() != null && param.getEndDate() != null) {
            wrapper.between(Order::getCreateTime, param.getStartDate(), param.getEndDate());
        }
        // 3. 执行分页查询
        IPage<Order> orderPage = orderMapper.selectPage(page, wrapper);
        return Result.success(orderPage);
    }

    @Override
    public Result<OrderDetailDTO> getOrderDetail(Integer orderId) {
        // 1. 查询订单主信息
        Order order = orderMapper.selectById(orderId);
        if (order == null) {
            return Result.error("订单不存在");
        }

        // 2. 查询关联的订单项
        LambdaQueryWrapper<OrderItem> itemWrapper = new LambdaQueryWrapper<>();
        itemWrapper.eq(OrderItem::getOrderId, orderId);
        List<OrderItem> items = orderItemMapper.selectList(itemWrapper);

        //查询用户地址
        UserAddress userAddress = userAddressMapper.selectById(order.getAddressId());
        // 3. 封装详情DTO
        OrderDetailDTO detailDTO = new OrderDetailDTO();
        detailDTO.setOrder(order);
        detailDTO.setItems(items);
        detailDTO.setUserAddress(userAddress);
        return Result.success(detailDTO);
    }

    @Override
    public Result<?> handleExceptionOrder(Integer orderId, String handleType, String remark) {
        // 1. 校验订单存在
        Order order = orderMapper.selectById(orderId);
        if (order == null) {
            return Result.error("订单不存在");
        }

        // 2. 根据处理类型更新订单状态
        if ("FORCE_CANCEL".equals(handleType)) {
            order.setStatus("canceled");
            order.setCancelTime(LocalDateTime.now());
            order.setExceptionReason("强制取消：" + remark);
        } else if ("RETRY_PROCESS".equals(handleType)) {
            order.setStatus("PENDING_PAYMENT");
            order.setExceptionReason("重试处理：" + remark);
        } else {
            return Result.error("不支持的处理类型");
        }
        // 3. 执行更新
        orderMapper.updateById(order);
        return Result.success("异常订单处理成功");
    }


    /**
     * 带有重试机制的锁获取方法
     */
    private RLock acquireLockWithRetry(String lockKey) {
        int retryTimes = 0;
        RLock lock = null;

        while (retryTimes < MAX_RETRY_TIMES) {
            try {
                lock = redissonClient.getLock(lockKey);
                // 尝试获取锁，等待3秒，锁自动释放时间10秒
                if (lock.tryLock(LOCK_WAIT_TIME, LOCK_LEASE_TIME, TimeUnit.SECONDS)) {
                    return lock;
                }
                retryTimes++;
                if (retryTimes < MAX_RETRY_TIMES) {
                    Thread.sleep(100); // 短暂等待后重试
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("获取锁被中断", e);
            } catch (Exception e) {
                log.error("获取锁失败，重试次数: {}", retryTimes, e);
                retryTimes++;
            }
        }

        throw new RuntimeException("获取分布式锁失败，请稍后重试");
    }

    /**
     * 创建订单实体
     */
    private Order createOrderEntity(OrderCreatDTO orderCreatDTO, Integer userId) {
        String orderNo = generateOrderNo();
        BigDecimal totalPrice = orderCreatDTO.getPrice()
                .multiply(BigDecimal.valueOf(orderCreatDTO.getQuantity()));

        Order order = new Order();
        order.setTotalPrice(totalPrice);
        order.setOrderNo(orderNo);
        order.setStatus("pending");
        order.setPayType("现金支付");
        order.setCreateTime(LocalDateTime.now());
        order.setUserId(userId);
        return order;
    }

    /**
     * 创建并保存订单项
     */
    private boolean createAndSaveOrderItem(OrderCreatDTO orderCreatDTO, Order order) {
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(order.getOrderId());
        orderItem.setProductId(orderCreatDTO.getProductId());//商品id
        orderItem.setQuantity(orderCreatDTO.getQuantity());//商品数量
        orderItem.setProductName(orderCreatDTO.getProductName());//商品名称
        orderItem.setUnitPrice(orderCreatDTO.getPrice());//商品单价
        orderItem.setImage(orderCreatDTO.getImage());//商品图片
        orderItem.setTotalPrice(order.getTotalPrice().multiply(BigDecimal.valueOf(orderCreatDTO.getQuantity())));//商品总价
        orderItem.setMerchantId(orderCreatDTO.getMerchantId());
        orderItem.setSpecs(orderCreatDTO.getSpecs());//商品规格
        orderItem.setCreateTime(order.getCreateTime());//创建时间
        orderItem.setIsDeleted(0);//未删除
        orderItem.setItemStatus("pending");
        return orderItemMapper.insert(orderItem) > 0;
    }

    private String generateOrderNo() {
        return UUID.randomUUID().toString().replace("-", "").toUpperCase().substring(0, 16);
    }


}